package net.godcode.olivenotes.entities;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;

/**
 * GenericHibernateDAO - based largely on concepts presented at
 * http://www.hibernate.org/328.html.
 * 
 * @author Chris Lewis Dec 26, 2007 <chris@thegodcode.net>
 * @version $Id: GenericHibernateDAO.java 32 2008-01-22 15:14:31Z burningodzilla $
 * @param <T> The entity type for which this DAO exists.
 * @param <ID> The identifier of this entity type.
 */
public abstract class GenericHibernateDAO<T, ID extends Serializable> implements GenericDAO<T, ID> {

	private Class<T> persistentClass;
	private Session session;

	@SuppressWarnings("unchecked")
	public GenericHibernateDAO() {
		this.persistentClass = (Class<T>)((ParameterizedType)getClass()
			.getGenericSuperclass())
			.getActualTypeArguments()[0];
	}
	
	/**
	 * Set the Hibernate Session.
	 * @param session
	 */
	public void setSession(Session session) {
		this.session = session;
	}
	
	/**
	 * Get the Hibernate Session.
	 * @return The Hibernate Session.
	 */
	protected Session getSession() {
		if(session == null) {
			throw new IllegalStateException("DAO session has not been set!");
		} else {
			return session;
		}
	}
	
	/**
	 * Get the persistent class (type) of this DAO.
	 * @return The type for which this DAO exists.
	 */
	public Class<T> getPersistentClass() {
		return persistentClass;
	}
	
	/* GenericDAO implementation. */
	
	public List<T> findAll() {
		Query q = getSession().createQuery("from " + persistentClass.getName());
		//q.setMaxResults(1); TODO support
		return (List<T>)q.list();
	}
	
	@SuppressWarnings("unchecked")
	public T findById(ID id) {
		return (T)getSession().load(getPersistentClass(), id);
	}
	
	public T save(T entity) {
		getSession().saveOrUpdate(entity);
		return entity;
	}

}